package com.atwisdom.star.core.bsl.modelClass.workCenter.Impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.atwisdom.star.common.actionType.modelClass.workCenter.WorkCenterActionType;
import com.atwisdom.star.common.util.JsonUtil;
import com.atwisdom.star.common.vo.*;
import com.atwisdom.star.core.bsl.modelClass.workCenter.WorkCenterInstanceBslService;
import com.atwisdom.star.core.dao.pojo.modelClass.workCenter.WorkCenterInstance;
import com.atwisdom.star.core.dsl.modelClass.consume.Impl.ConsumeInstanceDslServiceImpl;
import com.atwisdom.star.core.dsl.modelClass.hier.HierInstanceDslService;
import com.atwisdom.star.core.dsl.modelClass.hier.Impl.HierInstanceDslServiceImpl;
import com.atwisdom.star.core.dsl.modelClass.logic.Impl.LogicInstanceDslServiceImpl;
import com.atwisdom.star.core.dsl.modelClass.resource.Impl.ResourceInstanceDslServiceImpl;
import com.atwisdom.star.core.dsl.modelClass.tank.Impl.TankInstanceDslServiceImpl;
import com.atwisdom.star.core.dsl.modelClass.utils.*;
import com.atwisdom.star.core.dsl.modelClass.workCenter.Impl.WorkCenterInstanceDslServiceImpl;
import com.atwisdom.star.core.dsl.modelClass.workCenter.Impl.WorkCenterModelDslServiceImpl;
import com.atwisdom.star.exception.pojo.BusinessException;
import org.apache.commons.lang.StringUtils;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;

@Service
public class WorkCenterInstanceBslServiceImpl implements WorkCenterInstanceBslService {
    private WorkCenterModelDslServiceImpl workCenterModelDslService;
    private WorkCenterInstanceDslServiceImpl workCenterInstanceDslService;
    private LogicInstanceDslServiceImpl logicInstanceDslService;
    private ConsumeInstanceDslServiceImpl consumeInstanceDslService;
    private ResourceInstanceDslServiceImpl resourceInstanceDslService;

    private TankInstanceDslServiceImpl tankInstanceDslService;

    private HierInstanceDslService hierInstanceDslService;

    private QueryBuilder queryBuilder;

    @Autowired
    public void setLogicInstanceDslService(LogicInstanceDslServiceImpl logicInstanceDslService) {
        this.logicInstanceDslService = logicInstanceDslService;
    }

    @Autowired
    public void setConsumeInstanceDslService(ConsumeInstanceDslServiceImpl consumeInstanceDslService) {
        this.consumeInstanceDslService = consumeInstanceDslService;
    }

    @Autowired
    public void setResourceInstanceDslService(ResourceInstanceDslServiceImpl resourceInstanceDslService) {
        this.resourceInstanceDslService = resourceInstanceDslService;
    }

    @Autowired
    public void setWorkCenterModelDslService(WorkCenterModelDslServiceImpl workCenterModelDslService) {
        this.workCenterModelDslService = workCenterModelDslService;
    }

    @Autowired
    public void setWorkCenterInstanceDslService(WorkCenterInstanceDslServiceImpl workCenterInstanceDslService) {
        this.workCenterInstanceDslService = workCenterInstanceDslService;
    }

    @Autowired
    public void setTankInstanceDslService(TankInstanceDslServiceImpl tankInstanceDslService) {
        this.tankInstanceDslService = tankInstanceDslService;
    }

    @Autowired
    public void setHierInstanceDslService(HierInstanceDslServiceImpl hierInstanceDslService) {
        this.hierInstanceDslService = hierInstanceDslService;
    }

    @Autowired
    public void setQueryBuilder(QueryBuilder queryBuilder) {
        this.queryBuilder = queryBuilder;
    }


    /**
     * 服务工厂方法
     * @param actionDataList 参数
     * @return 参数
     * @throws BusinessException 异常
     */
    @Transactional
    public ResultInfo<?> responseFactory(List<ActionData<JSONObject>> actionDataList) throws BusinessException {
        ResultInfo<?> resultInfo = null;
        for (ActionData<JSONObject> actionData : actionDataList) {
            String action = actionData.getAction();
            WorkCenterActionType actionType = WorkCenterActionType.valueOf(action);
            String methodName = actionType.getMethodName();
            resultInfo = this.execMethod(methodName, actionData);
        }
        return resultInfo;
    }

    /**
     * 反射执行业务单元方法
     *
     * @param methodName 方法名
     * @param actionData 方法参数
     * @return 返回结果
     * @throws BusinessException 业务异常
     */
    public ResultInfo<?> execMethod(String methodName, ActionData<JSONObject> actionData) throws BusinessException {
        Class<? extends WorkCenterInstanceBslServiceImpl> clz = this.getClass();
        try {
            Method method = clz.getMethod(methodName, ActionData.class);
            WorkCenterInstanceBslServiceImpl service = (WorkCenterInstanceBslServiceImpl) AopContext.currentProxy();
            return (ResultInfo<?>) method.invoke(service, actionData);
        } catch (NoSuchMethodException ex) {
            throw new BusinessException("999999", "没有找到该方法(" + methodName + ")", ex);
        } catch (IllegalAccessException ex) {
            throw new BusinessException("999999", "没有访问该方法权限(" + methodName + ")", ex);
        } catch (InvocationTargetException ex) {
            Throwable targetException = ex.getTargetException();
            if (targetException instanceof BusinessException) {
                BusinessException bex = (BusinessException) targetException;
                throw new BusinessException("999999", bex.getErrorMsg(), ex);
            } else {
                throw new BusinessException("999999", "出错了请重试：(" + methodName + ")---" + ex.getMessage(), ex);
            }
        }
    }

    /**
     * 查询全部摘要（通用）
     *
     * @param actionData 参数
     * @return 返回值
     */
    @Override
    public ResultInfo<?> queryAllInfo(ActionData<JSONObject> actionData) {
        List<JSONObject> jsonObjectList = this.workCenterInstanceDslService.queryAllInfo();
        return JsonResult.success(jsonObjectList);
    }

    /**
     * 分页查询全部摘要（通用）
     *
     * @param actionData 参数
     * @return 返回值
     */
    @Override
    public ResultInfo<PageInfo> queryAllInfoByPage(ActionData<JSONObject> actionData) {
        int pageNumber = actionData.getPageNumber();
        int pageSize = actionData.getPageSize();
        String orderBy = actionData.getOrderBy();
        PageInfo pageInfo = this.workCenterInstanceDslService.queryAllInfoByPage(pageNumber, pageSize, orderBy);
        return JsonResult.success(pageInfo);
    }

    /**
     * 查询全部数据（通用）
     *
     * @param actionData 参数
     * @return 返回值
     */
    @Override
    public ResultInfo<?> queryAll(ActionData<JSONObject> actionData) {
        List<JSONObject> jsonObjectList = this.workCenterInstanceDslService.queryAll();
        return JsonResult.success(jsonObjectList);
    }

    /**
     * 分页查询全部数据（通用）
     *
     * @param actionData 参数
     * @return 返回值
     */
    @Override
    public ResultInfo<?> listAllByPage(ActionData<JSONObject> actionData) {
        int pageNumber = actionData.getPageNumber();
        int pageSize = actionData.getPageSize();
        String orderBy = actionData.getOrderBy();
        PageInfo pageInfo = this.workCenterInstanceDslService.listAllByPage(pageNumber, pageSize, orderBy);
        return JsonResult.success(pageInfo);
    }

    /**
     * 按条件查询模型
     *
     * @param actionData 参数
     * @return 返回值
     */
    @Override
    public ResultInfo<?> query(ActionData<JSONObject> actionData) {
        String condition = actionData.getCondition();
        String className = actionData.getClassName();
        String orderBy = actionData.getOrderBy();
        List<JSONObject> queryJsonList = this.workCenterInstanceDslService.query(condition, className, orderBy);
        return JsonResult.success(queryJsonList);
    }

    /**
     * 查询指定结点的子节点
     * @param actionData 参数
     * @return 返回结果
     */
    @Override
    public ResultInfo<?> queryHierByParentNodeId(ActionData<JSONObject> actionData) {
        Long instanceId = actionData.getInstanceId();
        String parentNodeId = actionData.getNodeId();
        String status = actionData.getStatus();
        JSONObject result = workCenterInstanceDslService.queryHierByParentNodeId(instanceId, parentNodeId, status);
        return JsonResult.success(result);
    }



    /**
     * 查询实例容器hier
     * @param actionData 参数
     * @return 返回hier
     */
    public ResultInfo<?> queryHierById(ActionData<JSONObject> actionData) {
        Long id = actionData.getId();
        JSONObject jsonObject = this.workCenterInstanceDslService.queryHierById(id);
        return JsonResult.success(jsonObject);
    }

    /**
     * 按条件分页查询模型实例摘要
     * @param actionData 参数
     * @return 返回结果
     */
    public ResultInfo<?> queryInfoByPage(ActionData<JSONObject> actionData) {
        int pageNumber = actionData.getPageNumber();
        int pageSize = actionData.getPageSize();
        String condition = actionData.getCondition();
        String className = actionData.getClassName();
        String orderBy = actionData.getOrderBy();
        PageInfo pageInfo = this.workCenterInstanceDslService.queryInfoByPage(pageNumber, pageSize, condition, className, orderBy);
        return JsonResult.success(pageInfo);
    }

    /**
     * 按条件分页查询模型实例
     * @param actionData 参数
     * @return 返回结果
     */
    public ResultInfo<?> queryByPage(ActionData<JSONObject> actionData) {
        int pageNumber = actionData.getPageNumber();
        int pageSize = actionData.getPageSize();
        String condition = actionData.getCondition();
        String className = actionData.getClassName();
        String orderBy = actionData.getOrderBy();
        String hierValueCondition = actionData.getHierValueCondition();
        PageInfo pageInfo = this.workCenterInstanceDslService.queryByPage(pageNumber, pageSize, condition, className, orderBy, hierValueCondition);
        return JsonResult.success(pageInfo);
    }

    /**
     * 根据ids获取实例数据
     *
     * @param actionData 参数
     * @return 返回实例
     */
    public ResultInfo<List<JSONObject>> queryByIds(ActionData<JSONObject> actionData) {
        List<Long> ids = actionData.getIds();
        List<JSONObject> resultList = workCenterInstanceDslService.queryByIds(ids);
        return JsonResult.success(resultList);
    }

    /**
     * 添加新模型
     *
     * @param actionData 参数
     * @return 返回值
     */
    @Override
    public ResultInfo<?> add(ActionData<JSONObject> actionData) {
        return this.initial(actionData);
    }

    /**
     * 初始化工艺路线实例
     *
     * @param actionData 参数
     * @return 反回工艺路线实例
     */
    @Override
    public ResultInfo<?> initial(ActionData<JSONObject> actionData){
        List<JSONObject> data = actionData.getData();
        JSONObject jsonObject = data.get(0);
        String type = jsonObject.getString("type");
        String className = jsonObject.getString("className");
        String name = jsonObject.getString("name");
        JSONObject values = jsonObject.getJSONObject("values");
        JSONObject hierProperties = workCenterModelDslService.queryHierProperties(className);
        this.initHierProperties(hierProperties);
        JSONObject addJson = this.workCenterInstanceDslService.add(type,className, name,values);
        return JsonResult.success(addJson);
    }


    /**
     * 处理hierProperties
     * @param hierProperties 参数
     * @return 返回hier json 结构
     */
    private JSONObject initHierProperties(JSONObject hierProperties) {
        if (hierProperties == null || hierProperties.size() < 1) {
            return new JSONObject();
        }

        String type = hierProperties.getString("type");
        if (StringUtils.isBlank(type)) {
            throw new BusinessException("999999", "工艺路线容器类型为空，操作失败！");
        }

        JSONObject hierJson = new JSONObject();
        switch (type) {
            case "list":
                hierJson = new JSONObject();
                break;
            case "dictionary":
                DictionaryHier dictionaryHier = new DictionaryHier(hierProperties);
                dictionaryHier.getContent().forEach(c -> this.createInstance(c.getLink()));
                hierJson = dictionaryHier.fetchJsonObject();
                break;
            case "tree":
                TreeHier treeHier = new TreeHier(hierProperties);
                treeHier.getContent().forEach(c -> this.createInstance(c.getLink()));
                hierJson = treeHier.fetchJsonObject();
                break;
            case "chain":
                ChainHier chainHier = new ChainHier(hierProperties);
                chainHier.getContent().forEach(c -> this.createInstance(c.getLink()));
                hierJson = chainHier.fetchJsonObject();
                break;
            case "treeChain":
                TreeChainHier treeChainHier = new TreeChainHier(hierProperties);
                treeChainHier.getContent().forEach(c -> this.createInstance(c.getLink()));
                hierJson = treeChainHier.fetchJsonObject();
                break;
            default:
                break;
        }

        return hierJson;
    }


    /**
     * 根据link 创建实例
     *
     * @param link 创建实例参数
     */
    private void createInstance(JSONObject link) {
        if (link == null) {
            return;
        }
        String id = link.getString("id");
        if (StringUtils.isNotBlank(id)) {
            return;
        }

        JSONObject values = link.getJSONObject("values");
        String type = link.getString("type");
        String className = link.getString("className");
        if (StringUtils.isBlank(type) || StringUtils.isBlank(className)) {
            return;
        }

        ModelType modelType = ModelType.getByCode(type);
        JSONObject jsonObject;
        switch (modelType){
            case Consume:
                jsonObject = consumeInstanceDslService.add(type, className, className,values);
                link.put("id",jsonObject.getString("id"));
                break;
            case Resource:
                jsonObject = resourceInstanceDslService.add(type, className, className,values);
                link.put("id",jsonObject.getString("id"));
                break;
            case Logic:
                jsonObject= logicInstanceDslService.add(type, className, className,values);
                link.put("id",jsonObject.getString("id"));
                break;
            case Tank:
                jsonObject= this.tankInstanceDslService.add(type,className,className,values);
                link.put("id",jsonObject.getString("id"));
                break;
            default:
                break;
        }
    }


    /**
     * 更新模型属性字段
     * 更新，需要同步更新实例，同步更新历史数据
     * 1、className 和 自定字段
     *
     * @param actionData 参数
     * @return 返回值
     */
    @Override
    public ResultInfo<?> updateById(ActionData<JSONObject> actionData) {
        List<JSONObject> data = actionData.getData();
        JSONObject updateJson = JsonUtil.toJSONObject(data.get(0));
        boolean updateNullFlag = actionData.isUpdateNullFlag();
        if(updateNullFlag){
            this.workCenterInstanceDslService.updateFieldNullById(updateJson);
        }
        JSONObject jsonObject = this.workCenterInstanceDslService.updateById(updateJson);
        return JsonResult.success(jsonObject);
    }

    /**
     * 更新实例hier
     * @param actionData 更新参数
     * @return 返回更新的实例
     */
    public ResultInfo<?>  updateHier(ActionData<JSONObject> actionData){
        List<JSONObject> data = actionData.getData();
        JSONObject jsonObject = data.get(0);
        Long id = jsonObject.getLong("id");
        String className = jsonObject.getString("className");
        JSONObject hier = jsonObject.getJSONObject("hier");
        JSONObject hierProperties = this.workCenterModelDslService.queryHierProperties(className);

        JSONObject hierJson = queryBuilder.fetchHierBy(hierProperties, hier);
        dealHierLinkInstance(hierJson);
        WorkCenterInstance workCenterInstance = this.workCenterInstanceDslService.queryById(id);
//        workCenterInstance.setHier(hierJson);

        //更新hier实例
        hierJson.put("containerId", workCenterInstance.getId());
        hierJson.put("containerModel", ModelType.WorkCenter.getCode());
        this.hierInstanceDslService.updateByContainerId(ModelType.Routing.getCode(), className, workCenterInstance.getId(), hierJson);


        JSONObject infoJsonObject = workCenterInstance.getInfoJsonObject();
        JSONObject resultJsonObject = workCenterInstanceDslService.updateById(infoJsonObject);
        return JsonResult.success(resultJsonObject);
    }

    /**
     * 处理hierLink
     *
     * @param hier 参数
     */
    private void dealHierLinkInstance(JSONObject hier) {
        JSONArray tempContent = hier.getJSONArray("content");
        JSONArray content = new JSONArray();
        for (int i = 0; i < tempContent.size(); i++) {
            JSONObject contentJson = tempContent.getJSONObject(i);
            JSONObject link = contentJson.getJSONObject("link");
            this.createInstance(link);
            contentJson.put("link", link);
            content.add(contentJson);
        }
        hier.put("content", content);
    }

    /**
     * 更新模型属性字段
     * 更新，需要同步更新实例，同步更新历史数据
     * 1、className 和 自定字段
     *
     * @param actionData 参数
     * @return 返回值
     */
    @Override
    public ResultInfo<?> updateByIds(ActionData<JSONObject> actionData) {
        List<JSONObject> jsonObjectList = this.workCenterInstanceDslService.updateByIds(actionData.getData());
        return JsonResult.success(jsonObjectList);
    }

    /**
     * 更新模型类型和类名（配置阶段）
     *
     * @param actionData 参数
     * @return 返回值
     */
    @Override
    public ResultInfo<?> updateClassName(ActionData<JSONObject> actionData) {
        List<JSONObject> data = actionData.getData();
        List<JSONObject> jsonObjectList = this.workCenterInstanceDslService.updateClassName(data.get(0));
        return JsonResult.success(jsonObjectList);
    }

    /**
     * 按ids删除模型
     *
     * @param actionData 参数
     * @return 返回值
     */
    @Override
    public ResultInfo<?> deleteByIds(ActionData<JSONObject> actionData) {
        List<Long> ids = actionData.getIds();
        this.workCenterInstanceDslService.deleteByIds(ids);
        return JsonResult.success(StatusCode.SUCCESS);
    }

    /**
     * 接className删除
     * 1、删除实例、2、删除历史 3、更新redis
     *
     * @param actionData 参数
     * @return 返回值
     */
    @Override
    public ResultInfo<?> deleteByClassName(ActionData<JSONObject> actionData) {
        String className = actionData.getClassName();
        this.workCenterInstanceDslService.deleteByClassName(className);
        return JsonResult.success(StatusCode.SUCCESS);
    }

    /**
     * 批量删除
     *
     * @param actionData 参数
     * @return 返回值
     */
    @Override
    public ResultInfo<?> deleteByClassNames(ActionData<JSONObject> actionData) {
        List<String> classNames = actionData.getClassNames();
        this.workCenterInstanceDslService.deleteByClassNames(classNames);
        return JsonResult.success(StatusCode.SUCCESS);
    }

    /**
     * 按Id 废除模型
     *
     * @param actionData 参数
     * @return 返回值
     */
    @Override
    public ResultInfo<?> repealByIds(ActionData<JSONObject> actionData) {
        List<Long> ids = actionData.getIds();
        this.workCenterInstanceDslService.repealByIds(ids);
        return JsonResult.success(StatusCode.SUCCESS);
    }

    /**
     * 批量废除
     *
     * @param actionData 参数
     * @return 返回值
     */
    @Override
    public ResultInfo<?> repealByClassNames(ActionData<JSONObject> actionData) {
        List<String> classNames = actionData.getClassNames();
        this.workCenterInstanceDslService.repealByClassNames(classNames);
        return JsonResult.success(StatusCode.SUCCESS);
    }

}
